package com.cloud.tsp.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.api.annotation.TransUser;
import com.cloud.core.exception.MyException;
import com.cloud.api.domain.tsp.*;
import com.cloud.api.myenum.CommandStatusEnum;
import com.cloud.mybatis.domain.TableDataInfo;
import com.cloud.tsp.config.MysqlConfig;
import com.cloud.tsp.mapper.CommandExecLatestMapper;
import com.cloud.tsp.service.ICommandExecHistoryService;
import com.cloud.tsp.service.ICommandExecLatestService;
import com.cloud.tsp.service.ICommandService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author haohaibo
 * @since 2023-11-29
 */
@Service("commandExecLatestService")
public class CommandExecLatestServiceImpl extends ServiceImpl<CommandExecLatestMapper, CommandExecLatest> implements ICommandExecLatestService {

    @Resource
    private CommandExecLatestMapper commandExecLatestMapper;
    @Resource
    private ICommandExecHistoryService commandExecHistoryService;
    @Resource
    private ICommandService commandService;
    @Resource
    private MessageSource messageSource;
    @Autowired
    private StreamBridge streamBridge;
    @Autowired
    private MysqlConfig mysqlConfig;
    @Resource(name = "myRedis")
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    @TransUser
    public TableDataInfo<CommandExecLatest> selectReview(QueryReview para) {
        Locale locale = LocaleContextHolder.getLocale();
        Page<CommandExecLatest>page = new Page<>();
        page.setCurrent(para.getPage());
        page.setSize(para.getPageSize());
        IPage<CommandExecLatest> data = commandExecLatestMapper.selectReview(page, para);
        for (CommandExecLatest cel : data.getRecords()) {
            Double timestamp = redisTemplate.opsForZSet().score("vehicle_state", cel.getVin());
            if (timestamp != null) {
                long between = ChronoUnit.SECONDS.between(LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp.longValue()), ZoneId.systemDefault()), LocalDateTime.now());
                if (between >= mysqlConfig.getSecond()) {
//                    cel.setVehicleStatus(messageSource.getMessage("vehicle.status.offline", null, locale));
                    cel.setVehicleStatus("offline");
                }else {
//                    cel.setVehicleStatus(messageSource.getMessage("vehicle.status.online", null, locale));
                    cel.setVehicleStatus("online");
                }
            }else {
//                cel.setVehicleStatus(messageSource.getMessage("vehicle.status.offline", null, locale));
                cel.setVehicleStatus("offline");
            }
//            cel.setStatus(CommandStatusEnum.getInstance(cel.getStatus()));
        }
        return TableDataInfo.build(data);
    }

    @Override
    public Long selectLockCount() {
        LambdaQueryWrapper<Command>queryCommand = new LambdaQueryWrapper<>();
        queryCommand.eq(Command::getFunctionCode,1);
        List<Command> list = commandService.list(queryCommand);
        List<String> collect = list.stream().map(Command::getId).collect(Collectors.toList());
        LambdaQueryWrapper<CommandExecLatest>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(CommandExecLatest::getCommand,collect);
        return commandExecLatestMapper.selectCount(queryWrapper);
    }

    @Override
    public void issueCommand(IssueCommand para) {
        Command command = commandService.getById(para.getCommand());
        if (command == null){
            throw new MyException("wds.exception.id");
        }
        List<CommandExecLatest> list = new ArrayList<>();
        for (String vin : para.getVin()){
            CommandExecLatest commandExecLatest = new CommandExecLatest();
            commandExecLatest.setId(vin+para.getCommand());
            commandExecLatest.setVin(vin);
            commandExecLatest.setCommand(para.getCommand());
            commandExecLatest.setStatus(String.valueOf(CommandStatusEnum.WAIT_VERIFY.getValue()));
            list.add(commandExecLatest);
        }
        this.saveOrUpdateBatch(list);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void examineCommand(ExamineCommand para) {
        List<CommandExecLatest> exist = commandExecLatestMapper.selectByIds(para.getIds());
        if (exist.size() == 0){
            throw new MyException("wds.exception.id");
        }
        examineResult(para);
        //保存历史
        List<CommandExecHistory> list = new ArrayList<>();
        for (String id : para.getIds()){
            CommandExecLatest data = commandExecLatestMapper.selectById(id);
            CommandExecHistory commandExecHistory = new CommandExecHistory();
            BeanUtils.copyProperties(data,commandExecHistory);
            commandExecHistory.setId(IdUtil.getSnowflakeNextIdStr());
            list.add(commandExecHistory);
        }
        commandExecHistoryService.saveBatch(list);
    }

    //执行审核
    public void examineResult(ExamineCommand para){
        List<CommandExecLatest> listLatest = new ArrayList<>();
        //0是审核通过
        if (para.getResult()==0){
            mqNotice(para.getIds());
            for (String id : para.getIds()){
                CommandExecLatest commandExecLatest = new CommandExecLatest();
                commandExecLatest.setId(id);
                commandExecLatest.setStatus(String.valueOf(CommandStatusEnum.ISSUED.getValue()));
                listLatest.add(commandExecLatest);
            }
        }else {
            for (String id : para.getIds()){
                CommandExecLatest commandExecLatest = new CommandExecLatest();
                commandExecLatest.setId(id);
                commandExecLatest.setStatus(String.valueOf(CommandStatusEnum.NOT_VERIFIED.getValue()));
                listLatest.add(commandExecLatest);
            }
        }
        this.updateBatchById(listLatest);
    }

    public void mqNotice(List<String> ids){
        List<CommandExecLatest> list = commandExecLatestMapper.selectByIds(ids);
        for (CommandExecLatest execLatest : list){
            String msg = execLatest.getVin()+"-"+execLatest.getCommand();
            streamBridge.send("tspcommand-out-0", MessageBuilder.withPayload(msg).build());
            System.out.println(msg);
        }
    }
}